Перейти к основному содержимому

5.01. Справочник по TypeScript

Разработчику Архитектору

Справочник по TypeScript

1. Основы типизации

Примитивные типы

TypeScript поддерживает следующие примитивные типы:

  • string — строка текста
  • number — числовое значение (включая целые и дробные)
  • boolean — логическое значение (true или false)
  • bigint — целое число произвольной длины
  • symbol — уникальный и неизменяемый идентификатор
  • undefined — значение, присваиваемое переменной, которая объявлена, но не инициализирована
  • null — явное отсутствие значения

Специальные типы

  • any — отключает проверку типов; переменная может принимать любое значение
  • unknown — безопасная альтернатива any; требует проверки перед использованием
  • never — тип, представляющий значения, которые никогда не возникают (например, функция, выбрасывающая ошибку или зацикливающаяся)
  • void — тип, указывающий отсутствие возвращаемого значения у функции

Тип object

Тип object описывает любой непримитивный тип. Он не включает null.

let obj: object = { a: 1 };
obj = [1, 2, 3];
obj = () => {};

Этот тип редко используется напрямую. Предпочтение отдается более точным описаниям структуры.


2. Составные типы

Объектные типы

Объектный тип описывает форму объекта через перечисление свойств и их типов:

type User = {
id: number;
name: string;
isActive: boolean;
};

Свойства могут быть опциональными:

type Config = {
theme?: 'light' | 'dark';
timeout?: number;
};

Свойства могут быть только для чтения:

type Point = {
readonly x: number;
readonly y: number;
};

Массивы

Массивы описываются двумя способами:

  • Синтаксис T[]:
    let numbers: number[] = [1, 2, 3];
  • Синтаксис Array<T>:
    let strings: Array<string> = ['a', 'b'];

Кортежи (Tuples)

Кортеж — массив фиксированной длины с известными типами элементов:

let rgb: [number, number, number] = [255, 128, 0];

Кортежи могут содержать опциональные элементы и остаточные параметры:

type HTTPResponse = [number, string?, ...string[]];

3. Объединения и пересечения

Объединение типов (|)

Объединение позволяет значению соответствовать одному из нескольких типов:

type ID = string | number;
type Status = 'loading' | 'success' | 'error';

Пересечение типов (&)

Пересечение объединяет несколько типов в один:

type A = { a: string };
type B = { b: number };
type C = A & B; // { a: string; b: number }

4. Функции

Типизация параметров и возврата

function greet(name: string): string {
return `Hello, ${name}`;
}

Функция может не возвращать значение:

function log(message: string): void {
console.log(message);
}

Необязательные и параметры по умолчанию

function createUser(name: string, age?: number) { /* ... */ }
function multiply(a: number, b: number = 1) { return a * b; }

Типы функций

Тип функции описывает сигнатуру:

type BinaryOperation = (x: number, y: number) => number;
const add: BinaryOperation = (a, b) => a + b;

Перегрузка функций

TypeScript поддерживает перегрузку функций через декларации:

function format(value: string): string;
function format(value: number): string;
function format(value: string | number): string {
return String(value);
}

5. Интерфейсы

Интерфейсы описывают контракты для объектов, классов и функций.

Базовый интерфейс

interface Person {
name: string;
age: number;
}

Расширение интерфейсов

interface Employee extends Person {
department: string;
}

Опциональные и readonly-свойства

interface Options {
timeout?: number;
readonly retries: number;
}

Индексные сигнатуры

interface Dictionary {
[key: string]: number;
}

Вызов и конструктор

interface Callable {
(input: string): boolean;
}

interface Constructable {
new (name: string): Instance;
}

6. Классы

Базовое объявление

class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
move() { console.log(`${this.name} moves`); }
}

Модификаторы доступа

  • public — доступен везде (по умолчанию)
  • private — доступен только внутри класса
  • protected — доступен внутри класса и его потомков

Параметры конструктора

class Point {
constructor(public x: number, public y: number) {}
}

Абстрактные классы

abstract class Shape {
abstract getArea(): number;
render() { /* общая логика */ }
}

Статические члены

class MathUtils {
static PI = 3.14159;
static double(x: number) { return x * 2; }
}

Реализация интерфейсов

class Bird implements Flyable {
fly() { /* ... */ }
}

7. Утилитарные типы

TypeScript предоставляет встроенные утилитарные типы для трансформации других типов.

Partial<T>

Делает все свойства типа T опциональными.

type PartialUser = Partial<User>; // { id?: number; name?: string; ... }

Required<T>

Делает все свойства обязательными.

Readonly<T>

Делает все свойства только для чтения.

Record<K, T>

Создает объектный тип с ключами типа K и значениями типа T.

type StatusCodeMap = Record<number, string>;

Pick<T, K>

Выбирает подмножество свойств из T по ключам K.

type NameOnly = Pick<User, 'name'>;

Omit<T, K>

Исключает указанные свойства из типа.

type WithoutId = Omit<User, 'id'>;

Exclude<T, U>

Исключает из T все типы, совместимые с U.

type NonNullable = Exclude<string | null | undefined, null | undefined>;

Extract<T, U>

Извлекает из T только те типы, которые совместимы с U.

NonNullable<T>

Удаляет null и undefined из объединения.

ReturnType<T>

Извлекает тип возвращаемого значения функции.

type R = ReturnType<() => string>; // string

Parameters<T>

Получает кортеж типов параметров функции.

type P = Parameters<(a: number, b: string) => void>; // [number, string]

ConstructorParameters<T>

Получает типы параметров конструктора.

InstanceType<T>

Получает тип экземпляра класса.

ThisType<T>

Указывает контекст this в объектных литералах.


8. Расширенные возможности типов

Условные типы

type IsString<T> = T extends string ? true : false;

Распределительные условные типы

Автоматически применяются к каждому элементу объединения.

Инференс в условных типах

type ReturnType<T> = T extends (...args: any) => infer R ? R : never;

Mapped Types

Создание новых типов на основе существующих с преобразованием ключей или значений.

type Nullable<T> = { [P in keyof T]: T[P] | null };

Template Literal Types

Позволяют создавать строки на основе шаблонов:

type EventName = `${'click' | 'hover'}-${'button' | 'link'}`;
// 'click-button' | 'click-link' | 'hover-button' | 'hover-link'

Key Remapping

В mapped types можно переименовывать ключи:

type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K]
};

9. Модули и пространства имен

Модули ES

TypeScript использует стандартные модули ES:

// math.ts
export const PI = 3.14159;
export function add(a: number, b: number) { return a + b; }

// main.ts
import { PI, add } from './math';

Пространства имен

namespace Utils {
export function log(msg: string) { console.log(msg); }
}

Пространства имен рекомендуются только для глобальных библиотек или legacy-кода.


10. Декларации

Глобальные декларации

declare var VERSION: string;
declare function initialize(): void;

Декларации модулей

declare module 'my-library' {
export function doSomething(): void;
}

Расширение существующих интерфейсов

interface Window {
myCustomProp: string;
}

11. Конфигурация TypeScript (tsconfig.json)

Полный список опций компилятора:

Основные настройки

  • target — версия ECMAScript (например, "ES2020", "ES2022")
  • module — система модулей ("commonjs", "es2020", "esnext")
  • lib — библиотеки, включаемые в компиляцию (["DOM", "ES2022"])
  • outDir — директория для скомпилированного JS
  • rootDir — корневая директория исходников
  • declaration — генерировать .d.ts файлы
  • sourceMap — генерировать source maps

Проверка типов

  • strict — включает все строгие проверки
  • noImplicitAny — запрещает неявный any
  • strictNullChecks — требует явной обработки null/undefined
  • strictFunctionTypes — усиливает проверку типов функций
  • strictBindCallApply — строгая типизация методов bind, call, apply
  • strictPropertyInitialization — требует инициализации всех свойств класса
  • noImplicitThis — запрещает неявный this типа any
  • alwaysStrict — добавляет "use strict" в каждый файл

Модули и разрешение

  • moduleResolution — стратегия разрешения модулей ("node", "classic")
  • baseUrl — базовый URL для абсолютных импортов
  • paths — маппинг путей
  • resolveJsonModule — разрешить импорт JSON-файлов
  • esModuleInterop — улучшает совместимость с CommonJS

JSX

  • jsx — режим обработки JSX ("preserve", "react", "react-jsx")
  • jsxFactory — функция для создания элементов (по умолчанию React.createElement)
  • jsxFragmentFactory — фабрика для фрагментов

Экспериментальные возможности

  • experimentalDecorators — поддержка декораторов
  • emitDecoratorMetadata — генерация метаданных для декораторов

Отладка и производительность

  • incremental — инкрементальная сборка
  • tsBuildInfoFile — файл для хранения информации о сборке
  • composite — поддержка проектных ссылок

Запреты и предупреждения

  • noUnusedLocals — предупреждать о неиспользуемых локальных переменных
  • noUnusedParameters — предупреждать о неиспользуемых параметрах
  • noImplicitReturns — требовать явный return во всех ветках
  • noFallthroughCasesInSwitch — запрет провалов в switch
  • allowUnreachableCode — разрешить недостижимый код
  • exactOptionalPropertyTypes — различать undefined и отсутствие свойства

12. Декораторы

Декораторы — экспериментальная возможность, позволяющая добавлять метаданные и изменять поведение классов, методов, свойств и параметров.

Включение декораторов

В tsconfig.json требуется:

{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}

Типы декораторов

  • Классовые декораторы:

    function sealed(constructor: Function) {
    Object.seal(constructor);
    Object.seal(constructor.prototype);
    }

    @sealed
    class Greeter { /* ... */ }
  • Метод-декораторы:

    function readonly(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    descriptor.writable = false;
    }

    class Math {
    @readonly
    double(x: number) { return x * 2; }
    }
  • Свойства-декораторы:

    function format(template: string) {
    return function (target: any, propertyKey: string) {
    // можно сохранить метаданные через Reflect
    };
    }

    class User {
    @format("Hello, %s")
    name: string;
    }
  • Параметр-декораторы:

    function logParameter(target: any, methodName: string, paramIndex: number) {
    // логика регистрации параметра
    }

    class Greeter {
    greet(@logParameter name: string) { /* ... */ }
    }

Метаданные

С включённой опцией emitDecoratorMetadata, TypeScript генерирует типы параметров и возвращаемых значений как метаданные, доступные через Reflect.getMetadata.


13. Работа с DOM и окружением

Глобальные типы

TypeScript автоматически подключает типы для DOM, если в lib указано "DOM".

Пример:

const button = document.getElementById('submit') as HTMLButtonElement;
button.addEventListener('click', () => { /* ... */ });

Определение глобальных переменных

// global.d.ts
interface Window {
__APP_VERSION__: string;
}

Теперь window.__APP_VERSION__ доступен без ошибок.

Работа с событиями

document.addEventListener('keydown', (event: KeyboardEvent) => {
if (event.key === 'Enter') { /* ... */ }
});

14. Интеграция с фреймворками

React

  • Используются файлы .tsx
  • Компоненты типизируются через React.FC<Props>
  • Хуки (useState, useEffect) выводят типы автоматически
  • Пропсы описываются интерфейсами или типами
interface ButtonProps {
label: string;
onClick: () => void;
}

const Button: React.FC<ButtonProps> = ({ label, onClick }) => (
<button onClick={onClick}>{label}</button>
);

Vue.js

  • Поддержка через defineComponent
  • Пропсы описываются в props с указанием типа
  • Композиционный API использует ref, computed с выводом типов
import { defineComponent, PropType } from 'vue';

export default defineComponent({
props: {
title: { type: String as PropType<string>, required: true }
},
setup(props) {
// props.title — string
}
});

Angular

  • Полная поддержка TypeScript «из коробки»
  • Декораторы @Component, @Injectable используют метаданные
  • Типизация шаблонов через строгую проверку

Node.js

  • Устанавливается пакет @types/node
  • Глобальные объекты: process, global, Buffer
  • Модули CommonJS и ES совместимы при правильной настройке
import * as fs from 'fs';
fs.readFile('file.txt', 'utf8', (err, data) => { /* ... */ });

15. Распространённые паттерны

Защита от null/undefined (Defensive Programming)

function processUser(user: User | null) {
if (!user) return;
// user теперь User
}

Discriminated Unions

type Success = { status: 'success'; data: string };
type Failure = { status: 'error'; message: string };
type Result = Success | Failure;

function handle(result: Result) {
if (result.status === 'success') {
// result.data доступен
}
}

Type Guards

function isString(value: unknown): value is string {
return typeof value === 'string';
}

if (isString(input)) {
// input — string
}

Branding Types (Nominal Typing Emulation)

type UserID = string & { readonly brand: unique symbol };
const createUserID = (id: string): UserID => id as UserID;

Immutability

Использование Readonly<T>, readonly массивов и spread-операторов:

const newState = { ...state, count: state.count + 1 };

16. Лучшие практики

  • Всегда включайте strict: true
  • Избегайте any; используйте unknown при работе с внешними данными
  • Предпочитайте interface для публичных API, type — для утилит и union-типов
  • Используйте утилитарные типы вместо ручного копирования структур
  • Пишите тесты с учётом типов (Jest + ts-jest)
  • Разделяйте бизнес-логику и типы от инфраструктурного кода
  • Не используйте as без необходимости; предпочитайте проверки типов

17. Инструменты и CLI

Компилятор tsc

Основные команды:

  • tsc --init — создаёт tsconfig.json
  • tsc --watch — отслеживает изменения и перекомпилирует
  • tsc --noEmit — только проверка типов, без генерации JS
  • tsc file.ts — компиляция одного файла

ESLint + TypeScript

  • Используется @typescript-eslint/parser
  • Правила: no-explicit-any, strict-boolean-expressions, prefer-readonly

Prettier

Форматирование кода с поддержкой TypeScript и JSX.

TypeScript Playground

Онлайн-редактор на typescriptlang.org/play


18. Расширение TypeScript

AST и трансформеры

TypeScript предоставляет API для анализа и модификации Abstract Syntax Tree.

Пример использования:

import * as ts from 'typescript';

const source = ts.createSourceFile('test.ts', 'const x = 1;', ts.ScriptTarget.Latest);

Это используется в:

  • Кастомных линтерах
  • Кодогенераторах
  • Babel-плагинах с поддержкой TS
  • Framework-specific компиляторах (например, Angular)

Language Service API

Позволяет создавать IDE-функции: автодополнение, навигацию, рефакторинг.